package c6;

import java.util.*;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toCollection;

/**
 * 分组
 */
public class Grouping {
    public static void main(String[] args) {
        Map<Dish.Type, List<Dish>> dishesByType=Dish.menu.stream().collect(Collectors.groupingBy(Dish::getType));
        System.out.println(dishesByType);

        //按照热量分为三组
        Map<CaloricLevel,List<Dish>> dishesByCaloricLevel=Dish.menu.stream()
                .collect(Collectors.groupingBy(dish->{
                    if(dish.getCalories()<400){
                        return CaloricLevel.DIET;
                    }else if(dish.getCalories()<=700){
                        return CaloricLevel.NORMAL;
                    }else{
                        return CaloricLevel.FAT;
                    }
                }));
        System.out.println(dishesByCaloricLevel);

        //每种类型菜肴多少个
        Map<Dish.Type,Long> typesCount=Dish.menu.stream()
                .collect(Collectors.groupingBy(Dish::getType,Collectors.counting()));
        System.out.println(typesCount);

        //查找每个子组中热量最高的dish，把收集器的结果转换为另一种类型
        Map<Dish.Type, Dish> mostCaloricByType =Dish.menu.stream()
                .collect(
                        Collectors.groupingBy(Dish::getType,
                        Collectors.collectingAndThen(Collectors.maxBy(Comparator.comparingInt(Dish::getCalories)),Optional::get))
                );
        //idea推荐的写法

//        Map<Dish.Type, Dish> mostCaloricByType =Dish.menu.stream()
//                .collect(
//                        Collectors.toMap(Dish::getType, Function.identity(), BinaryOperator.maxBy(Comparator.comparingInt(Dish::getCalories)))
//                );
        System.out.println(mostCaloricByType);

        //grouping 和mapping结合
        Map<Dish.Type, Set<CaloricLevel>> caloricLevelsByType =
                Dish.menu.stream().collect(
                        Collectors.groupingBy(Dish::getType, Collectors.mapping(
                                dish -> { if (dish.getCalories() <= 400) return CaloricLevel.DIET;
                                else if (dish.getCalories() <= 700) return CaloricLevel.NORMAL;
                                else return CaloricLevel.FAT; },
                                toCollection(HashSet::new) )));
        System.out.println(caloricLevelsByType);

    }

    public enum CaloricLevel{
        DIET,
        NORMAL,
        FAT
    }
}
